import { Service } from 'egg';
import { Op } from 'sequelize';
import { RESULT_CODE } from '../utils/constants/code';

type ListType = 'sent' | 'received';
type ProcessAction = 'accept' | 'reject' | 'cancel';

export default class ExclusiveRestaurantInviteService extends Service {
  // 根据手机号查用户，并附带该餐厅下的邀请状态
  async findUserByMobileWithInviteStatus(params: { restaurant_id: number; mobile: string }) {
    const { ctx } = this;
    const userId = ctx.state.user.user_id;
    const { restaurant_id, mobile } = params;

    if (!restaurant_id || !mobile) ctx.throw(RESULT_CODE.FAIL, 'restaurant_id 与 mobile 必填');

    // 校验餐厅归属与状态：仅 owner 可查询
    const restaurant = await ctx.model.ExclusiveRestaurant.findOne({
      where: { id: Number(restaurant_id), user_id: userId, status: 'approved' },
    });
    if (!restaurant) ctx.throw(403, '无权查询该餐厅的邀请信息');

    // 查找用户
    const user = await ctx.model.User.findOne({
      where: { mobile: String(mobile) },
      attributes: ['user_id', 'user_name', 'mobile', 'avatar'],
    });

    if (!user) {
      return { user: null, invite: null };
    }

    if(user.avatar) {
      user.avatar = this.config.host + user.avatar;
    }

    // 查找邀请状态
    const invite = await ctx.model.ExclusiveRestaurantInvite.findOne({
      where: { restaurant_id: Number(restaurant_id), invitee_id: (user as any).user_id },
      attributes: ['id', 'status'],
    });

    return {
      user,
      invite: invite ? invite : null,
    };
  }
  // 我的邀请列表
  async listInvites(params: { type: ListType; page?: number; limit?: number }) {
    const { ctx } = this;
    const userId = ctx.state.user.user_id;
    const { type, page = 1, limit = 10 } = params;

    const where: any = {};
    if (type === 'sent') where.inviter_id = userId;
    if (type === 'received') where.invitee_id = userId;

    const offset = (Number(page) - 1) * Number(limit);

    const { count, rows } = await ctx.model.ExclusiveRestaurantInvite.findAndCountAll({
      where,
      order: [['created_at', 'DESC']],
      limit: Number(limit),
      offset,
      include: [
        { model: ctx.model.ExclusiveRestaurant, as: 'restaurant' },
        { model: ctx.model.User, as: 'inviter', attributes: ['user_name', 'mobile'] },
        { model: ctx.model.User, as: 'invitee', attributes: ['user_name', 'mobile'] },
      ],
    });

    return {
      list: rows,
      total: count,
      page: Number(page),
      limit: Number(limit),
    };
  }

  // 我接受邀请的餐厅列表
  async listAcceptedRestaurants(params: { page?: number; limit?: number }) {
    const { ctx } = this;
    const userId = ctx.state.user.user_id;
    const { page = 1, limit = 10 } = params;
    const offset = (Number(page) - 1) * Number(limit);

    const { count, rows } = await ctx.model.ExclusiveRestaurantInvite.findAndCountAll({
      where: { invitee_id: userId, status: 'accepted' },
      order: [['created_at', 'DESC']],
      limit: Number(limit),
      offset,
      include: [{ model: ctx.model.ExclusiveRestaurant, as: 'restaurant' }],
    });

    const restaurants = rows.map(r => (r as any).restaurant).filter(Boolean);

    // 处理图片
    const newRestaurants = restaurants.map(restaurant => {
      const restaurantData = restaurant!.toJSON() as any;
      if(restaurantData.pictures) {
        restaurantData.imgList = restaurantData.pictures ? restaurantData.pictures.split(',').map(i => ({ url: this.config.host + i, path: i })) : [];
      }
      return restaurantData;
    });

    return {
      list: newRestaurants,
      total: count,
      page: Number(page),
      limit: Number(limit),
    };
  }

  // 发出邀请
  async sendInvite(payload: { restaurant_id: number; invitee_id: number; remark?: string }) {
    const { ctx } = this;
    const userId = ctx.state.user.user_id;
    const { restaurant_id, invitee_id, remark } = payload;

    // 校验餐厅归属：只能由该餐厅的owner发出
    const restaurant = await ctx.model.ExclusiveRestaurant.findOne({
      where: { id: restaurant_id, user_id: userId, status: 'approved' },
    });
    if (!restaurant) ctx.throw(403, '无权为该餐厅发出邀请');

    if (invitee_id === userId) ctx.throw(RESULT_CODE.FAIL, '不能邀请自己');

    // 去重规则：若存在 pending 或 accepted 的邀请，阻止重复
    const existed = await ctx.model.ExclusiveRestaurantInvite.findOne({
      where: {
        restaurant_id,
        invitee_id,
        status: { [Op.in]: ['pending', 'accepted'] },
      },
    });
    if (existed) ctx.throw(RESULT_CODE.FAIL, '存在未处理或已接受的邀请');

    const row = await ctx.model.ExclusiveRestaurantInvite.create({
      restaurant_id,
      inviter_id: userId,
      invitee_id,
      status: 'pending',
      remark,
    });
    return row;
  }

  // 处理邀请
  async processInvite(payload: { id: number; action: ProcessAction }) {
    const { ctx } = this;
    const userId = ctx.state.user.user_id;
    const { id, action } = payload;

    const invite = await ctx.model.ExclusiveRestaurantInvite.findByPk(id);
    if (!invite) ctx.throw(RESULT_CODE.FAIL, '邀请不存在');

    const row: any = invite;

    if (action === 'cancel') {
      // 只有发起人或该餐厅owner可以取消
      const restaurant = await ctx.model.ExclusiveRestaurant.findOne({
        where: { id: row.restaurant_id, status: 'approved' },
      });
      const isOwner = restaurant && (restaurant as any).user_id === userId;
      if (row.inviter_id !== userId && !isOwner) ctx.throw(403, '无权取消该邀请');
      if (row.status !== 'pending') ctx.throw(RESULT_CODE.FAIL, '当前状态不可取消');
      await row.update({ status: 'canceled' });
      return { message: '取消成功' };
    }

    // accept/reject 仅被邀请人可处理
    if (row.invitee_id !== userId) ctx.throw(403, '无权处理该邀请');
    if (row.status !== 'pending') ctx.throw(RESULT_CODE.FAIL, '当前状态不可处理');

    if (action === 'accept') {
      await row.update({ status: 'accepted' });
      return { message: '已接受邀请' };
    }
    if (action === 'reject') {
      await row.update({ status: 'rejected' });
      return { message: '已拒绝邀请' };
    }

    ctx.throw(RESULT_CODE.FAIL, '不支持的操作');
  }

  // 工具：校验用户是否对某餐厅有已接受邀请
  async assertUserAcceptedInvite(restaurant_id: number, user_id: number) {
    const { ctx } = this;
    const invite = await ctx.model.ExclusiveRestaurantInvite.findOne({
      where: { restaurant_id, invitee_id: user_id, status: 'accepted' },
    });
    if (!invite) ctx.throw(403, '仅受邀用户可操作');
  }
}